package edu.uwm.cs552;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

/**
 * Main frame for the hexagonal board editor.
 * By default hidden geography is visible.
 */
public class HexBoardEditor extends JFrame {

	/**
	 * Keep Eclipse happy
	 */
	private static final long serialVersionUID = 1L;
	private HexBoardPanel hexBoardPanel;
	private HexBoard hexBoard;
	private JComboBox editActionComboBox;
	private JCheckBox meshCheckBox, showHiddenBox;

	private static final int DEFAULT_WIDTH = 75;
	private static final int DEFAULT_HEIGHT = 50;
	
	
	private static final HexBoardEditAction defaultEditAction = new TerrainDraw(Terrain.PLAIN);
	private static final HexBoardEditAction[] editActions = new HexBoardEditAction[]{
		new TerrainDraw(null), defaultEditAction, new TerrainDraw(Terrain.MOUNTAIN), 
		new TerrainDraw(Terrain.DESERT), new TerrainDraw(Terrain.SMALL), 
		new TerrainDraw(Terrain.MEDIUM), new TerrainDraw(Terrain.LARGE), 
		new TerrainDraw(Terrain.SUBURB),
		new BarrierDraw(null), new BarrierDraw(Barrier.BLOCK), 
		new BarrierDraw(Barrier.INLET), new BarrierDraw(Barrier.RIVER),
		new BarrierDraw(Barrier.DRAWN)
	};

	public HexBoardEditor() {
		super("Hex Board Editor");
		/*for (int a=0; a < 100; ++a) {
			for (int b=0; b < 100; ++b) {
				cont.put(new HexCoordinate(a,b),Terrain.PLAIN);
			}
		}*/
		//HexBoard b = new HexBoard(new SVGImageCreator(new URL("file:lib/amnord01.svg")),105,148.5,cont);
		//hexBoard = new HexBoard(new SVGImageCreator(new URL("file:lib/usa-plus.svg")),66,54,cont);
		hexBoard = new HexBoard(null,DEFAULT_WIDTH,DEFAULT_HEIGHT);
		getContentPane().setLayout(new BorderLayout());
		hexBoardPanel = new HexBoardPanel(hexBoard);
		MouseAdapter mouseActions = new MouseAdapter(){
			@Override
			public void mouseDragged(MouseEvent arg0) {
				editMap(arg0.getPoint());
			}
			@Override
			public void mousePressed(MouseEvent arg0) {
				editMap(arg0.getPoint());
			}
		};
		hexBoardPanel.addMouseListener(mouseActions);
		hexBoardPanel.addMouseMotionListener(mouseActions);
		getContentPane().add(new JScrollPane(hexBoardPanel));
		JPanel panel = new JPanel();
		panel.add(new JLabel("Magnification:"));
		panel.add(new ScaleComboBox(hexBoardPanel));
		editActionComboBox = new JComboBox(editActions);
		editActionComboBox.setRenderer(new HexBoardEditActionRenderer());
		panel.add(editActionComboBox);
		editActionComboBox.setSelectedItem(defaultEditAction);
		editActionComboBox.setMaximumRowCount(editActions.length);
		showHiddenBox = new JCheckBox("Show Hidden");
		showHiddenBox.setSelected(true);
		hexBoardPanel.setShowHidden(true);
		panel.add(showHiddenBox);
		showHiddenBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg) {
				showHiddenChangeRequested();
			}
		});
		meshCheckBox = new JCheckBox("Show Hex Mesh");
		meshCheckBox.setSelected(false);
		panel.add(meshCheckBox);
		meshCheckBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg) {
				meshChangeRequested();
			}
		});
		
		getContentPane().add(panel,BorderLayout.NORTH);
				
		JMenuBar bar = new JMenuBar();
		JMenu fileMenu = new JMenu("File");
		JMenuItem newItem = new JMenuItem("New");
		JMenuItem openItem = new JMenuItem("Open...");
		JMenuItem saveItem = new JMenuItem("Save");
		JMenuItem saveAsItem = new JMenuItem("Save As...");
		JMenuItem quitItem = new JMenuItem("Quit");
		
		newItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doNew();
			}
		});
		openItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doOpen();
			}
		});
		saveItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doSave();
			}
		});
		saveAsItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doSaveAs();
			}
		});
		quitItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doQuit();
			}
		});
		
		fileMenu.add(newItem);
		fileMenu.add(openItem);
		fileMenu.addSeparator();
		fileMenu.add(saveItem);
		fileMenu.add(saveAsItem);
		fileMenu.addSeparator();
		fileMenu.add(quitItem);
		bar.add(fileMenu);
		setJMenuBar(bar);
		
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter(){
			@Override
			public void windowClosing(WindowEvent we) {
				doQuit();
			}
		});
	}
	
	
	private void editMap(Point p) {
		final double scale = hexBoardPanel.getScale();
		((HexBoardEditAction)(editActionComboBox.getSelectedItem())).apply(hexBoard, p, scale);
	}

	public void showHiddenChangeRequested() {
		hexBoardPanel.setShowHidden(showHiddenBox.isSelected());
	}
	
	public void meshChangeRequested() {
		hexBoardPanel.setDrawMesh(meshCheckBox.isSelected());
	}

	private final HexBoardDialog newDialog = new HexBoardDialog(this);
	private static File file = null;
	
	private void doNew() {
		newDialog.setVisible(true);
		if (newDialog.getResult() != null) {
			hexBoard.copy(newDialog.getResult());
			file = null;
		}
	}
	
	JFileChooser fileChooser = new JFileChooser();
	
	private void doOpen() {
		switch (fileChooser.showOpenDialog(this)) {
		case JFileChooser.APPROVE_OPTION:
			try {
				File f = fileChooser.getSelectedFile();
				BufferedReader br = new BufferedReader(new FileReader(f));
				hexBoard.read(br);
				br.close();
				file = f;
			} catch (Exception e) {
				JOptionPane.showMessageDialog(this, e.getMessage(), "Error opening file", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	private void doSave() {
		if (file == null) doSaveAs();
		else doSave(file);
	}
	
	private void doSave(File f) {
		try {
			/*
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
			oos.writeObject(hexBoard);
			oos.close();
			*/
			PrintWriter pw = new PrintWriter(new FileWriter(f));
			hexBoard.write(pw);
			pw.close();
			if (pw.checkError()) throw new IOException("File writing failed");
			file = f;
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, e.getMessage(), "Error saving file", JOptionPane.ERROR_MESSAGE);
		}
	}
	
	private void doSaveAs() {
		switch (fileChooser.showSaveDialog(this)) {
		case JFileChooser.APPROVE_OPTION:
			doSave(fileChooser.getSelectedFile());
		}		
	}
	
	private void doQuit() {
		if (JOptionPane.showConfirmDialog(this, "Really Quit?", "Confirm Exit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
			System.exit(0);
		}
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				HexBoardEditor hbe = new HexBoardEditor();
				hbe.setSize(500,300);
				hbe.setVisible(true);
			}
		});
	}
}
